package com.kuaimacode.kframework.api.controller.pay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.kuaimacode.kframework.api.controller.BaseController;
import com.kuaimacode.kframework.api.service.*;
import com.kuaimacode.kframework.api.service.user.OrderDispatchService;
import com.kuaimacode.kframework.api.service.user.OrderEvaluateService;
import com.kuaimacode.kframework.api.service.user.OrderService;
import com.kuaimacode.kframework.common.Constant;
import com.kuaimacode.kframework.common.JsonResult;
import com.kuaimacode.kframework.constants.MasterConstants;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.models.master.MasterOrderAccitity;
import com.kuaimacode.kframework.mybatis.models.user.*;
import com.kuaimacode.kframework.util.CommonUtil;
import com.kuaimacode.kframework.util.DictUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;

@RestController
@RequestMapping("/alipay")
@Api(tags = "支付宝支付相关",description = "支付宝支付相关")
public class AlipayController  extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderEvaluateService orderEvaluateService;
    @Autowired
    private UserRechargeService userRechargeService;
    @Autowired
    private MasterOrderAccitityService accitityService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserAccountDetailService userAccountDetailService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private OrderDispatchService orderDispatchService;

    // 获取配置文件中支付宝相关信息
    @Value("${pay.alipay.aliPayGateway}")
    private String aliPayGateway;
    @Value("${pay.alipay.aliPayAppId}")
    private String aliPayAppId;
    @Value("${pay.alipay.rsaPublicKey}")
    private String rsaPublicKey;
    @Value("${pay.alipay.rsaPrivatKey}")
    private String rsaPrivatKey;
    @Value("${pay.alipay.rsaAlipayPublicKey}")
    private String rsaAlipayPublicKey;
    @Value("${pay.alipay.signType}")
    private String signType;
    @Value("${pay.alipay.alipayFormat}")
    private String alipayFormat;
    @Value("${pay.alipay.alipayCharset}")
    private String alipayCharset;
    @Value("${pay.alipay.notify}")
    private String notify;

    @ApiOperation(value = "生成APP支付订单信息", notes="生成APP支付订单信息")
    @PostMapping("/prepare")
    @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataType = "string")
    @Transactional
    public JsonResult prepare(@RequestParam String orderNo,
                              HttpServletRequest request){
        // 获取项目中实际的订单的信息
        // 此处是相关业务代码
        Order order = orderService.findOrderByOrderNo(orderNo+"");
        Optional.ofNullable(order).filter(o->o.getStatus() == Constant.OrderStatusEnum.WAIT_PAY.getCode())
                .orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));

        // 开始使用支付宝SDK中提供的API
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);
        // 注意：不同接口这里的请求对象是不同的，这个可以查看蚂蚁金服开放平台的API文档查看
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("阿四服务订单");

        String subject = "阿四服务订单-";
        if(order.getHasPartner() == 1){
            subject = subject+"合作商家订单";
        }else{
            String type = DictUtil.keyValue("SERVICE_CLASS",order.getType()+"");
            String childTypeCode = "SERVICE_CLASS_"+order.getType();
            String childType = DictUtil.keyValue(childTypeCode,order.getChildType()+"");
            subject = subject +type+"-"+childType;
        }

        model.setSubject(subject);//
        // 唯一订单号 根据项目中实际需要获取相应的
        model.setOutTradeNo(order.getOutTradeNo());
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(order.getAmount().toString());
        //model.setTotalAmount("0.01");//测试使用0.01
        model.setProductCode("QUICK_MSECURITY_PAY");
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);

        // 注意：每个请求的相应对象不同，与请求对象是对应。
        AlipayTradeAppPayResponse alipayResponse = null;
        try {
            alipayResponse = alipayClient.sdkExecute(alipayRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //保存支付类型
        order.setPayType(Constant.PayTypeEnum.ALIPAY.getCode());
        orderService.saveOrUpdate(order);
        // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
        return JsonResult.success(alipayResponse.getBody());
        //return ResponseEntity.status(HttpStatus.OK).body(alipayResponse.getBody());
    }


    @PostMapping("/notify")
    @Transactional
    public String notify(HttpServletRequest request){
        // 解决POST请求中文乱码问题（推荐使用此种方式解决中文乱码，因为是支付宝发送异步通知使用的是POST请求）
        try {
            request.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            // 官方demo中使用如下方式解决中文乱码，在此本人不推荐使用，可能会出现中文乱码解决无效的问题。
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            params.put(name, valueStr);
        }

        // 支付宝公钥（请注意，不是商户公钥）
        boolean signVerified = false;
        try {
            //调用SDK验证签名
            signVerified = AlipaySignature.rsaCheckV1(params, rsaAlipayPublicKey, alipayCharset, signType);
            if(signVerified) {
                // 验证通知后执行自己项目需要的业务操作
                // 一般需要判断支付状态是否为TRADE_SUCCESS
                // 更严谨一些还可以判断 1.appid 2.sellerId 3.out_trade_no 4.total_amount 等是否正确，正确之后再进行相关业务操作。
                String out_trade_no = params.get("out_trade_no");
                String trade_status = params.get("trade_status");
                logger.error("支付宝回调业务处理开始:" + params);
                // 支付成功或
                if ("TRADE_SUCCESS".equals(trade_status)
                        || "TRADE_FINISHED".equals(trade_status)) {
                    // 处理支付成功逻辑
                    try {
                        if(out_trade_no.startsWith(Constant.REWARD_OUT_TRADE_NO_PRE)){
                            //订单评价打赏回调
                            OrderEvaluate orderEvaluate = orderEvaluateService.findByOutTradeNo(out_trade_no);
                            if(orderEvaluate != null){
                                //完成师傅余额增长
                                //修改余额
                                User user = userService.getById(orderEvaluate.getMasterId());
                                BigDecimal balance = Optional.ofNullable(orderEvaluate.getReward()).orElse(BigDecimal.ZERO).add(user.getAccountBalance());
                                user.setAccountBalance(balance);
                                if(userService.updateById(user)){
                                    //保存余额变动明细
                                    UserAccountDetail userAccountDetail = new UserAccountDetail();
                                    userAccountDetail.setAccountType("1");
                                    userAccountDetail.setAccoutWay(Long.parseLong(String.valueOf(orderEvaluate.getPayType())));
                                    userAccountDetail.setAmount(orderEvaluate.getReward().toString());
                                    userAccountDetail.setCreateDt(new Date());
                                    userAccountDetail.setDetailType("2");
                                    userAccountDetail.setInOutType("3");
                                    userAccountDetail.setTranDesc("订单打赏:"+orderEvaluate.getOrderId());
                                    userAccountDetail.setUserId(orderEvaluate.getMasterId());
                                    userAccountDetail.setTranAmount(user.getAccountBalance());
                                    userAccountDetail.setStatus("0");
                                    Order order = orderService.getById(orderEvaluate.getOrderId());
                                    userAccountDetail.setOutTradeNo(order.getOrderNo());
                                    userAccountDetailService.save(userAccountDetail);
                                    //更新状态
                                    String trade_no = params.get("trade_no");
                                    orderEvaluate.setPayAt(new Date());
                                    orderEvaluate.setTransNo(trade_no);
                                    orderEvaluate.setRewardStatus(1);//已支付
                                    if(orderEvaluateService.updateById(orderEvaluate)){
                                        //通知推送师傅
                                        if(orderEvaluate.getMasterId() != null) {
                                            sysMessageService.saveMessage("用户打赏订单", "用户打赏订单[" + orderEvaluate.getOrderId() + "]", true, orderEvaluate.getMasterId());
                                        }
                                    }
                                }else{
                                    logger.error("支付宝回调业务处理【打赏】，师傅余额变动失败:" + out_trade_no);
                                }
                            }else{
                                logger.error("支付宝回调业务处理【打赏】，评价数据不存在:" + out_trade_no);
                            }
                        }else if(out_trade_no.startsWith(Constant.RECHARGE_TRADE_NO_PRE)){
                            //充用户充值回调
                            UserRecharge userRecharge = userRechargeService.findByOutTradeNo(out_trade_no);
                            if(userRecharge != null){
                                //完成师傅余额增长
                                //修改余额
                                User user = userService.getById(userRecharge.getUserId());
                                BigDecimal balance = Optional.ofNullable(userRecharge.getAmount()).orElse(BigDecimal.ZERO).add(user.getAccountBalance());
                                user.setAccountBalance(balance);
                                if(userService.updateById(user)){
                                    //保存余额变动明细
                                    UserAccountDetail userAccountDetail = new UserAccountDetail();
                                    userAccountDetail.setAccountType("1");
                                    userAccountDetail.setAccoutWay(Long.parseLong(String.valueOf(userRecharge.getPayType())));
                                    userAccountDetail.setAmount(userRecharge.getAmount().toString());
                                    userAccountDetail.setCreateDt(new Date());
                                    userAccountDetail.setDetailType("2");
                                    userAccountDetail.setInOutType("3");
                                    userAccountDetail.setTranDesc("充值");
                                    userAccountDetail.setUserId(userRecharge.getUserId());
                                    userAccountDetail.setStatus("0");
                                    userAccountDetail.setTranAmount(user.getAccountBalance());
                                    userAccountDetailService.save(userAccountDetail);
                                    //更新状态
                                    String trade_no = params.get("trade_no");
                                    userRecharge.setPayAt(new Date());
                                    userRecharge.setTransNo(trade_no);
                                    userRecharge.setStatus(2);//已支付
                                    if(userRechargeService.updateById(userRecharge)){
                                        //通知推送师傅
                                        if(userRecharge.getUserId() != null) {
                                            sysMessageService.saveMessage("用户充值", "用户充值[" + userRecharge.getAmount().toString() + "元]成功到账", true, userRecharge.getUserId());
                                        }
                                    }
                                }else{
                                    logger.error("支付宝回调业务处理【充值】，用户余额变动失败:" + out_trade_no);
                                }
                            }else{
                                logger.error("支付宝回调业务处理【充值】，充值记录不存在:" + out_trade_no);
                            }
                        }else if(out_trade_no.startsWith(Constant.COLLECTION_OUT_TRADE_NO_PRE)){
                            //订单代收货款回调
                            Order order = orderService.findOrderByCollectionOutTradeNo(out_trade_no);
                            //this.check(params, order);
                            String trade_no = params.get("trade_no");
                            order.setCollectionPayStatus(Constant.CollectionPayStatusEnum.PAYED.getCode());//订单状态设为待接单
                            order.setCollectionTransNo(trade_no);//交易流水号，退款用
                            order.setUpdateAt(new Date());
                            if (orderService.updateById(order)){
                                //修改订单流程状态
                                MasterOrderAccitity orderAccitity = accitityService.getMasterAccitityByOrderId(order.getId(),null);
                                if(orderAccitity != null){
                                    orderAccitity.setCurrentStatus(MasterConstants.MasterOrderCurrentStatus.STATUS_7.getCode());
                                    accitityService.updateById(orderAccitity);
                                }
                                //通知推送师傅
                                if(order.getMasterId() != null) {
                                    sysMessageService.saveMessage("用户支付代收货款", "用户支付代收货款：" + order.getCollectionAmount()
                                            + ",订单[" + order.getOrderNo() + "]", true, order.getMasterId());
                                }
                            }
                        }else if(out_trade_no.startsWith(Constant.FEE_OUT_TRADE_NO_PRE)){
                            //技术服务费不定价回调
                            Order order = orderService.findOrderByFeeOutTradeNo(out_trade_no);
                            String trade_no = params.get("trade_no");
                            order.setFeePayStatus(Constant.CollectionPayStatusEnum.PAYED.getCode());//订单状态设为待接单
                            order.setFeeTransNo(trade_no);//交易流水号，退款用
                            order.setUpdateAt(new Date());
                            if (orderService.updateById(order)){
                                //修改订单流程状态
                                MasterOrderAccitity orderAccitity = accitityService.getMasterAccitityByOrderId(order.getId(),null);
                                if(orderAccitity != null){
                                    //不定价服务结束计时
                                    orderAccitity.setEndTime(new Date());
                                    orderAccitity.setCurrentStatus(MasterConstants.MasterOrderCurrentStatus.STATUS_7.getCode());
                                    accitityService.updateById(orderAccitity);
                                }
                                //通知推送师傅
                                if(order.getMasterId() != null) {
                                    sysMessageService.saveMessage("用户支付订单服务费", "用户支付订单服务费" + order.getAnyhelpFee()
                                            + ",订单[" + order.getOrderNo() + "]", true, order.getMasterId());
                                }
                            }
                        }else if(out_trade_no.startsWith(Constant.OUT_TRADE_NO_PRE)){
                            Order order = orderService.findOrderByOutTradeNo(out_trade_no);
                            this.check(params, order);
                            //普通订单回调
                            String trade_no = params.get("trade_no");
                            order.setStatus(Constant.OrderStatusEnum.WAIT_ACCEPT.getCode());//订单状态设为待接单
                            order.setTransNo(trade_no);//交易流水号，退款用
                            order.setUpdateAt(new Date());
                            orderService.updateById(order);
                            try {
                                //如果是抢单加人工派单，则给师傅发送通知
                                orderDispatchService.newOrderPush(order);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }else{
                            logger.error("支付宝回调业务处理,未知的out_trade_no,params:" + params);
                        }
                    } catch (Exception e) {
                        logger.error("支付宝回调业务处理报错,params:" + params, e);
                    }
                } else {
                    logger.error("没有处理支付宝回调业务，支付宝交易状态：{},params:{}",trade_status,params);
                }

                // 成功要返回success，不然支付宝会不断发送通知。
                return "success";
            }

            // 验签失败  笔者在这里是输出log，可以根据需要做一些其他操作
            logger.error("支付宝回调业务验签报错,params:" + params);
            // 失败要返回success，不然支付宝会不断发送通知。
            return "fail";
        } catch (AlipayApiException e) {
            e.printStackTrace();
            logger.error("支付宝回调业务验签异常,params:" + params);
            // 验签异常  笔者在这里是输出log，可以根据需要做一些其他操作
            return "fail";
        }
    }

    /**
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     *
     * @param params
     * @throws AlipayApiException
     */
    private void check(Map<String, String> params, Order order) throws AlipayApiException {
        String outTradeNo = params.get("out_trade_no");

        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        if (order == null) {
            throw new AlipayApiException("out_trade_no错误");
        }

        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        /*BigDecimal total_amount = new BigDecimal(params.get("total_amount"));
        if (total_amount.compareTo(order.getAmount()) != 0) {
            throw new AlipayApiException("error total_amount"+params.get("total_amount"));
        }*/

        // 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
        // 第三步可根据实际情况省略

        // 4、验证app_id是否为该商户本身。
        if (!params.get("app_id").equals(aliPayAppId)) {
            throw new AlipayApiException("app_id不一致");
        }
    }


    /**
     * 支付订单退款
     * 支付宝原路退回
     * @param order
     * @return
     */
    public boolean refound(Order order, BigDecimal amount){
        Optional.ofNullable(order).orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        logger.error("支付宝退款开始:" + order.getOrderNo());
        //支付宝支付
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
        refundModel.setTradeNo(order.getTransNo());
        if(amount == null){
            refundModel.setRefundAmount(order.getAmount().toString());
        }else{
            refundModel.setRefundAmount(amount.toString());
        }
        refundModel.setRefundReason("阿四服务订单退款"+order.getOrderNo());
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizModel(refundModel);
        try{
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            System.out.println(response.getMsg()+"\n");
            System.out.println(response.getBody());
            if(response.isSuccess()){
                return true;
            }
        }catch(Exception e){
            e.printStackTrace();
            logger.error("支付宝退款错误！",e.getMessage());
        }
        return false;
    }


    @ApiOperation(value = "生成APP支付二维码信息（代收货款）", notes="返回二维码对应的url，自行生成二维码")
    @PostMapping("/qrcode")
    @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataType = "string")
    public JsonResult qrcode(@RequestParam String orderNo, HttpServletRequest request){
        //System.setProperty("proxyType", "4");
//        System.setProperty("http.proxyHost", "proxyUrl");
//        System.setProperty("http.proxyPort", "proxyPort");

        // 获取项目中实际的订单的信息
        // 此处是相关业务代码
        Order order = orderService.findOrderByOrderNo(orderNo);
        if(order == null){
            throw new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST);
        }
        // 开始使用支付宝SDK中提供的API
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);
        /*// 注意：不同接口这里的请求对象是不同的，这个可以查看蚂蚁金服开放平台的API文档查看
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        String type = DictUtil.keyValue("SERVICE_CLASS",order.getType()+"");
        String childTypeCode = "SERVICE_CLASS_"+order.getType();
        String childType = DictUtil.keyValue(childTypeCode,order.getChildType()+"");
        String subject = "阿四服务订单-"+type+"-"+childType;

        model.setBody("阿四服务订单");
        model.setSubject(subject);//
        // 唯一订单号 根据项目中实际需要获取相应的
        model.setOutTradeNo(order.getOutTradeNo());
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(order.getAmount().toString());
        //model.setProductCode("FACE_TO_FACE_PAYMENT");
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);

        // 注意：每个请求的相应对象不同，与请求对象是对应。
        AlipayTradePrecreateResponse alipayResponse = null;
        try {
            alipayResponse = alipayClient.sdkExecute(alipayRequest);
            MasterOrderAccitity orderAccitity = accitityService.getMasterAccitityByOrderId(order.getId(),null);
            if(orderAccitity != null){
                orderAccitity.setCurrentStatus(MasterConstants.MasterOrderCurrentStatus.STATUS_7.getCode());
                accitityService.updateById(orderAccitity);
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            JsonResult.failure("生成失败");
        }*/

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        /*String type = DictUtil.keyValue("SERVICE_CLASS",order.getType()+"");
        String childTypeCode = "SERVICE_CLASS_"+order.getType();
        String childType = DictUtil.keyValue(childTypeCode,order.getChildType()+"");
        String subject = "阿四服务订单-"+type+"-"+childType;*/
        String subject = "阿四服务订单"+"-代收货款";

        if(order.getCollectionAmount() == null || order.getCollectionAmount().compareTo(BigDecimal.ZERO)<=0){
            //如果有代收货款
            throw new ServerInternalErrorException(ErrorEnum.NO_COLLECTION_AMOUNT);
        }


        model.setBody("阿四服务订单");
        model.setSubject(subject);//
        // 唯一订单号 根据项目中实际需要获取相应的
        model.setOutTradeNo(order.getCollectionOutTradeNo());
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(order.getCollectionAmount().toString());
        //model.setTotalAmount("0.01");//测试使用0.01
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);
        Map map = new HashMap();
        map.put("amount",order.getCollectionAmount());
        String qr_code = "";
        try {
            alipayRequest.setBizModel(model);
            alipayRequest.setNotifyUrl(notify);
            AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
            qr_code = response.getBody();
            map.put("qrCode",qr_code);

            //JSONObject jsonObject = JSONObject.parseObject(response.getBody());
            //qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
        return JsonResult.success(map);
    }

    @ApiOperation(value = "生成APP支付二维码信息（技术服务不定价收款）", notes="返回二维码对应的url，自行生成二维码")
    @PostMapping("/qrcodeForFee")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataType = "string"),
            @ApiImplicitParam(name = "fee", value = "技术服务费（不定价）", required = true, dataType = "string")
    })
    public JsonResult qrcodeForFee(@RequestParam String orderNo, @RequestParam BigDecimal fee){

        // 此处是相关业务代码
        Order order = orderService.findOrderByOrderNo(orderNo);
        if(order == null){
            throw new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST);
        }

        if(fee == null || fee.compareTo(BigDecimal.ZERO)<=0){
            throw new ServerInternalErrorException(ErrorEnum.PARAM_VALID_ERROR);
        }

        if(order.getFeeOutTradeNo() == null){
            throw new ServerInternalErrorException(ErrorEnum.PARAM_VALID_ERROR);
        }

        // 开始使用支付宝SDK中提供的API
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
        String subject = "阿四服务订单"+"-技术服务费";

        model.setBody("阿四服务订单");
        model.setSubject(subject);//
        // 唯一订单号 根据项目中实际需要获取相应的
        model.setOutTradeNo(order.getFeeOutTradeNo());
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(fee.toString());
        //model.setTotalAmount("0.01");//测试使用0.01
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);
        Map map = new HashMap();
        map.put("amount",fee);
        String qr_code = "";
        try {
            alipayRequest.setBizModel(model);
            alipayRequest.setNotifyUrl(notify);
            AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
            qr_code = response.getBody();
            map.put("qrCode",qr_code);
            order.setAnyhelpFee(fee);
            order.setPayType(Constant.PayTypeEnum.ALIPAY.getCode());
            //order.setCollectionPayStatus(2);
            orderService.updateById(order);
            //JSONObject jsonObject = JSONObject.parseObject(response.getBody());
            //qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
        return JsonResult.success(map);
    }

    @ApiOperation(value = "订单打赏支付参数生成", notes="订单打赏支付参数生成")
    @PostMapping("/reward")
    @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataType = "string")
    @Transactional
    public JsonResult reward(@RequestParam String orderNo, HttpServletRequest request){
        Order order = orderService.findOrderByOrderNo(orderNo);
        Optional.ofNullable(order) .orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        OrderEvaluate orderEvaluate = orderEvaluateService.findOneByOrderId(order.getId());
        Optional.ofNullable(orderEvaluate).filter(o->o.getRewardStatus() == 0)
                .orElseThrow(()->new ServerInternalErrorException(ErrorEnum.DATA_NOT_EXIST));
        if(orderEvaluate.getReward() == null || orderEvaluate.getReward().compareTo(BigDecimal.ZERO)<=0){
            throw new ServerInternalErrorException(ErrorEnum.DATA_NOT_EXIST);
        }
        // 开始使用支付宝SDK中提供的API
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);
        // 注意：不同接口这里的请求对象是不同的，这个可以查看蚂蚁金服开放平台的API文档查看
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("阿四服务订单打赏");
        String subject = "阿四服务订单"+orderEvaluate.getOrderId()+"打赏";
        model.setSubject(subject);
        //String outTradeNo = CommonUtil.generateOrderNum(Constant.REWARD_OUT_TRADE_NO_PRE, orderEvaluate.getOrderId());
        //orderEvaluate.setOutTradeNo(outTradeNo);
        model.setOutTradeNo(orderEvaluate.getOutTradeNo());
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(orderEvaluate.getReward().toString());
        //model.setTotalAmount("0.01");//测试使用0.01
        model.setProductCode("QUICK_MSECURITY_PAY");
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);

        // 注意：每个请求的相应对象不同，与请求对象是对应。
        AlipayTradeAppPayResponse alipayResponse = null;
        try {
            alipayResponse = alipayClient.sdkExecute(alipayRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //保存支付类型
        orderEvaluate.setPayType(Constant.PayTypeEnum.ALIPAY.getCode());
        orderEvaluateService.saveOrUpdate(orderEvaluate);
        // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
        return JsonResult.success(alipayResponse.getBody());
    }


    @ApiOperation(value = "用户充值支付参数生成", notes="用户充值支付参数生成")
    @PostMapping("/recharge")
    @ApiImplicitParam(name = "amount", value = "金额", required = true, dataType = "string")
    @Transactional
    public JsonResult recharge(@RequestParam BigDecimal amount){
        if(amount == null){
            throw new ServerInternalErrorException(ErrorEnum.PARAM_VALID_ERROR);
        }
        // 开始使用支付宝SDK中提供的API
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType);
        // 注意：不同接口这里的请求对象是不同的，这个可以查看蚂蚁金服开放平台的API文档查看
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("阿四服务充值");
        String subject = "阿四服务充值订单："+amount.toString();
        model.setSubject(subject);
        String outTradeNo = CommonUtil.generateOrderNum(Constant.RECHARGE_TRADE_NO_PRE, getUserId());
        model.setOutTradeNo(outTradeNo);
        // 支付超时时间（根据项目需要填写）
        model.setTimeoutExpress("30m");
        // 支付金额（项目中实际订单的需要支付的金额，金额的获取与操作请放在服务端完成，相对安全）
        model.setTotalAmount(amount.toString());
        //model.setTotalAmount("0.01");//测试使用0.01
        model.setProductCode("QUICK_MSECURITY_PAY");
        alipayRequest.setBizModel(model);
        // 支付成功后支付宝异步通知的接收地址url
        alipayRequest.setNotifyUrl(notify);

        // 注意：每个请求的相应对象不同，与请求对象是对应。
        AlipayTradeAppPayResponse alipayResponse = null;
        try {
            alipayResponse = alipayClient.sdkExecute(alipayRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //保存充值记录
        UserRecharge ur = new UserRecharge();
        ur.setAmount(amount);
        ur.setOutTradeNo(outTradeNo);
        ur.setCreateAt(new Date());
        ur.setDeleteState(1);//正常
        //保存支付类型
        ur.setPayType(Constant.PayTypeEnum.ALIPAY.getCode());
        ur.setStatus(1);//支付中
        ur.setUserId(getUserId());
        userRechargeService.save(ur);
        // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
        return JsonResult.success(alipayResponse.getBody());
    }
}
